home *** CD-ROM | disk | FTP | other *** search
/ Micromanía 92 / CDMM92_1.ISO / SOF 2 SDK / sof2sdk-101.msi / _92D6AC311BB48EBA344BBABC89DA6AB0 / _569B0EAC24D54B08A41DDDDDBA6993CF < prev    next >
Encoding:
Text File  |  2002-06-05  |  7.7 KB  |  314 lines

  1. // Copyright (C) 2001-2002 Raven Software.
  2. //
  3. // cg_playerstate.c -- this file acts on changes in a new playerState_t
  4. // With normal play, this will be done after local prediction, but when
  5. // following another player or playing back a demo, it will be checked
  6. // when the snapshot transitions like all the other entities
  7.  
  8. #include "cg_local.h"
  9.  
  10. /*
  11. ==============
  12. CG_DamageFeedback
  13. ==============
  14. */
  15. void CG_DamageFeedback( int yawByte, int pitchByte, int damage ) 
  16. {
  17.     float        kick;
  18.     int            health;
  19.     float        scale;
  20.     vec3_t        dir;
  21.     vec3_t        angles;
  22.  
  23.     // show the attacking player's head and name in corner
  24.     cg.attackerTime = cg.time;
  25.  
  26.     // the lower on health you are, the greater the view kick will be
  27.     health = cg.snap->ps.stats[STAT_HEALTH];
  28.     if ( health < 40 ) 
  29.     {
  30.         scale = 1;
  31.     } 
  32.     else 
  33.     {
  34.         scale = 40.0 / health;
  35.     }
  36.  
  37.     kick = damage * scale;
  38.  
  39.     if (kick < 5)
  40.         kick = 5;
  41.     if (kick > 10)
  42.         kick = 10;
  43.  
  44.     // if yaw and pitch are both 255, make the damage always centered (falling, etc)
  45.     if ( yawByte == 255 && pitchByte == 255 ) 
  46.     {
  47.         cg.damageX = 0;
  48.         cg.damageY = 0;
  49.         cg.v_dmg_roll = 255;
  50.         cg.v_dmg_pitch = -kick;
  51.     } 
  52.     else 
  53.     {
  54.         float front;
  55.         float left;
  56.  
  57.         angles[PITCH] = (float)pitchByte / 255.0f * 360.0f;
  58.         angles[YAW]   = (float)yawByte / 255.0f * 360.0f;
  59.         angles[ROLL]  = 0;
  60.  
  61.         AngleVectors( angles, dir, NULL, NULL );
  62.         VectorSubtract( vec3_origin, dir, dir );
  63.  
  64.         front = DotProduct (dir, cg.refdef.viewaxis[0] );
  65.         left = DotProduct (dir, cg.refdef.viewaxis[1] );
  66.  
  67.         cg.v_dmg_roll = kick * left;        
  68.         cg.v_dmg_pitch = -kick * front;
  69.  
  70.         cg.damageY = -AngleNormalize180(angles[PITCH]);
  71.         cg.damageX = AngleNormalize180(angles[YAW] - cg.predictedPlayerState.viewangles[YAW] + 180);
  72.     }
  73.  
  74.     // don't let the screen flashes vary as much
  75.     if ( kick > 10 ) 
  76.     {
  77.         kick = 10;
  78.     }
  79.  
  80.     cg.damageTime = cg.snap->serverTime;
  81. }
  82.  
  83.  
  84.  
  85.  
  86. /*
  87. ================
  88. CG_Respawn
  89.  
  90. A respawn happened this snapshot
  91. ================
  92. */
  93. void CG_Respawn( void ) 
  94. {
  95.     // no error decay on player movement
  96.     cg.thisFrameTeleport = qtrue;
  97.  
  98.     // display weapons available
  99.     cg.weaponSelectTime = cg.time;
  100.  
  101.     // select the weapon the server says we are using
  102.     cg.weaponSelect = cg.snap->ps.weapon;
  103.  
  104.     // no more camera shake
  105.     cg.shakeStart = 0;
  106.  
  107.     // Make sure the weapon selection menu isnt up
  108.     cg.weaponMenuUp = qfalse;
  109.  
  110.     // clear any left over flash grenades
  111.     cg.flashbangTime = 0;
  112.  
  113.     // Reset the animation
  114.     CG_SetWeaponAnim( cg.snap->ps.weaponAnimId&(~ANIM_TOGGLEBIT), &cg.snap->ps );
  115.  
  116.     // Update the view weapon surfaces
  117.     CG_UpdateViewWeaponSurfaces ( &cg.snap->ps );
  118.  
  119.     trap_ResetAutorun ( );
  120. }
  121.  
  122. extern char *eventnames[];
  123.  
  124. /*
  125. ==============
  126. CG_CheckPlayerstateEvents
  127. ==============
  128. */
  129. void CG_CheckPlayerstateEvents( playerState_t *ps, playerState_t *ops ) 
  130. {
  131.     int            i;
  132.     int            event;
  133.     centity_t    *cent;
  134.  
  135.     if ( ps->externalEvent && ps->externalEvent != ops->externalEvent ) 
  136.     {
  137.         cent = CG_GetEntity ( ps->clientNum );
  138.         cent->currentState.event = ps->externalEvent;
  139.         cent->currentState.eventParm = ps->externalEventParm;
  140.         CG_EntityEvent( cent, cent->lerpOrigin );
  141.     }
  142.  
  143.     cent = &cg_entities[ ps->clientNum ];
  144.  
  145.     // go through the predictable events buffer
  146.     for ( i = ps->eventSequence - MAX_PS_EVENTS ; i < ps->eventSequence ; i++ ) {
  147.         // if we have a new predictable event
  148.         if ( i >= ops->eventSequence
  149.             // or the server told us to play another event instead of a predicted event we already issued
  150.             // or something the server told us changed our prediction causing a different event
  151.             || (i > ops->eventSequence - MAX_PS_EVENTS && ps->events[i & (MAX_PS_EVENTS-1)] != ops->events[i & (MAX_PS_EVENTS-1)]) ) {
  152.  
  153.             event = ps->events[ i & (MAX_PS_EVENTS-1) ];
  154.             cent->currentState.event = event;
  155.             cent->currentState.eventParm = ps->eventParms[ i & (MAX_PS_EVENTS-1) ];
  156.             CG_EntityEvent( cent, cent->lerpOrigin );
  157.  
  158.             cg.predictableEvents[ i & (MAX_PREDICTED_EVENTS-1) ] = event;
  159.  
  160.             cg.eventSequence++;
  161.         }
  162.     }
  163. }
  164.  
  165. /*
  166. ==================
  167. CG_CheckChangedPredictableEvents
  168. ==================
  169. */
  170. void CG_CheckChangedPredictableEvents( playerState_t *ps ) 
  171. {
  172.     int            i;
  173.     int            event;
  174.     centity_t    *cent;
  175.  
  176.     cent = &cg_entities[ps->clientNum];
  177.     for ( i = ps->eventSequence - MAX_PS_EVENTS ; i < ps->eventSequence ; i++ ) 
  178.     {
  179.         //
  180.         if (i >= cg.eventSequence) 
  181.         {
  182.             continue;
  183.         }
  184.         // if this event is not further back in than the maximum predictable events we remember
  185.         if (i > cg.eventSequence - MAX_PREDICTED_EVENTS) 
  186.         {
  187.             // if the new playerstate event is different from a previously predicted one
  188.             if ( ps->events[i & (MAX_PS_EVENTS-1)] != cg.predictableEvents[i & (MAX_PREDICTED_EVENTS-1) ] ) 
  189.             {
  190.                 event = ps->events[ i & (MAX_PS_EVENTS-1) ];
  191.                 cent->currentState.event = event;
  192.                 cent->currentState.eventParm = ps->eventParms[ i & (MAX_PS_EVENTS-1) ];
  193.                 CG_EntityEvent( cent, cent->lerpOrigin );
  194.  
  195.                 cg.predictableEvents[ i & (MAX_PREDICTED_EVENTS-1) ] = event;
  196.  
  197.                 if ( cg_showmiss.integer ) 
  198.                 {
  199.                     Com_Printf("WARNING: changed predicted event\n");
  200.                 }
  201.             }
  202.         }
  203.     }
  204. }
  205.  
  206. /*
  207. ==================
  208. CG_CheckLocalSounds
  209. ==================
  210. */
  211. void CG_CheckLocalSounds( playerState_t *ps, playerState_t *ops ) 
  212. {
  213.     // don't play the sounds if the player just changed teams
  214.     if ( ps->persistant[PERS_TEAM] != ops->persistant[PERS_TEAM] ) 
  215.     {
  216.         return;
  217.     }
  218.  
  219.     // health changes of more than -1 should make pain sounds
  220.     if ( ps->stats[STAT_HEALTH] < ops->stats[STAT_HEALTH] - 1 ) 
  221.     {
  222.         if ( ps->stats[STAT_HEALTH] > 0 ) 
  223.         {
  224.             CG_PainEvent( &cg_entities[ps->clientNum], ps->stats[STAT_HEALTH] );
  225.         }
  226.     }
  227.  
  228.     // Look for a zoom transition that isnt the first zoom in
  229.     if ( ops->zoomFov && (ps->zoomFov != ops->zoomFov) )
  230.     {
  231.         trap_S_StartLocalSound ( cgs.media.zoomSound, CHAN_AUTO );
  232.     }
  233. }
  234.  
  235. /*
  236. ===============
  237. CG_TransitionPlayerState
  238. ===============
  239. */
  240. void CG_TransitionPlayerState( playerState_t *ps, playerState_t *ops ) 
  241. {
  242.     // respawning.  This is done before the follow mode check because spawn count is 
  243.     // maintained into the following client
  244.     if ( ps->persistant[PERS_SPAWN_COUNT] != ops->persistant[PERS_SPAWN_COUNT] ) 
  245.     {
  246.         CG_Respawn();
  247.     }
  248.  
  249.     // check for changing follow mode
  250.     if ( ps->clientNum != ops->clientNum ) 
  251.     {
  252.         cg.thisFrameTeleport = qtrue;
  253.         // make sure we don't get any unwanted transition effects
  254.         *ops = *ps;
  255.     }
  256.  
  257.     // damage events (player is getting wounded)
  258.     if ( ps->damageEvent != ops->damageEvent && ps->damageCount ) 
  259.     {
  260.         CG_DamageFeedback( ps->damageYaw, ps->damagePitch, ps->damageCount );
  261.     }
  262.  
  263.     // Make sure we clear the weapon menu when we die
  264.     if ( ps->stats[STAT_HEALTH] != ops->stats[STAT_HEALTH] )
  265.     {
  266.         if ( ps->stats[STAT_HEALTH] <= 0 )
  267.         {
  268.             cg.weaponMenuUp = qfalse;
  269.             cg.deathTime = cg.time;
  270.             trap_ResetAutorun ( );
  271.         }
  272.     }
  273.  
  274.     if ( cg.mapRestart ) 
  275.     {
  276.         CG_Respawn();
  277.         cg.mapRestart = qfalse;
  278.     }
  279.  
  280.     if ( cg.snap->ps.pm_type != PM_INTERMISSION && ps->persistant[PERS_TEAM] != TEAM_SPECTATOR ) 
  281.     {
  282.         CG_CheckLocalSounds( ps, ops );
  283.     }
  284.  
  285.     // Always use the weapon from the player state when following
  286.     if( (ps->pm_flags & PMF_FOLLOW) || (ps->weapon != ops->weapon) )
  287.     {
  288.         cg.weaponSelect = ps->weapon;
  289.     }
  290.  
  291.     // Check for weapon animation change.
  292.     if(ps->weaponAnimId!=ops->weaponAnimId )
  293.     {
  294.         CG_SetWeaponAnim(ps->weaponAnimId&(~ANIM_TOGGLEBIT),ps);
  295.     }
  296.  
  297.     // run events
  298.     CG_CheckPlayerstateEvents( ps, ops );
  299.  
  300.     // smooth the ducking viewheight change and not crouch jumping
  301.     if ( ps->viewheight != ops->viewheight && !(ps->pm_flags & PMF_CROUCH_JUMP) ) 
  302.     {
  303.         cg.duckChange = ps->viewheight - ops->viewheight;
  304.         cg.duckTime = cg.time;
  305.     }
  306.  
  307.     // Need to update the view weapon surfaces when weapon states change
  308.     if ( ps->weaponstate != ops->weaponstate )
  309.     {
  310.         CG_UpdateViewWeaponSurfaces ( ps );
  311.     }
  312. }
  313.  
  314.